import java.lang.annotation.*;
import java.util.Arrays;
import java.util.List;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

// 定义权限注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermission {
    String[] value(); // 需要的权限标识
}

// 实现权限检查切面
@Aspect
@Component
public class PermissionAspect {

    // 环绕通知处理权限检查
    @Around("@annotation(requiresPermission)")
    public Object checkPermission(ProceedingJoinPoint joinPoint,
                                  RequiresPermission requiresPermission) throws Throwable {

        // 获取当前请求中的用户权限
        List<String> userPermissions = getCurrentUserPermissions();

        // 获取方法需要的权限
        List<String> requiredPermissions = Arrays.asList(requiresPermission.value());

        // 检查权限
        if (!hasPermissions(userPermissions, requiredPermissions)) {
            throw new AccessDeniedException("Access denied. Required permissions: " + requiredPermissions);
        }

        // 执行目标方法
        return joinPoint.proceed();
    }

    // 从请求中获取当前用户权限
    private List<String> getCurrentUserPermissions() {
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        // 从请求头获取权限
        String permissionsHeader = attributes.getRequest().getHeader("X-User-Permissions");
        return permissionsHeader != null ?
                Arrays.asList(permissionsHeader.split(",")) :
                List.of();
    }

    // 检查用户是否拥有所需权限
    private boolean hasPermissions(List<String> userPermissions, List<String> requiredPermissions) {
        return userPermissions.containsAll(requiredPermissions);
    }
}

// 自定义访问拒绝异常
public class AccessDeniedException extends RuntimeException {
    public AccessDeniedException(String message) {
        super(message);
    }
}

// 全局异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<String> handleAccessDenied(AccessDeniedException ex) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ex.getMessage());
    }
}

// 在Controller中使用装饰器
@RestController
@RequestMapping("/api/products")
public class ProductController {

    // 需要产品读取权限
    @GetMapping
    @RequiresPermission("product:read")
    public List<Product> getAllProducts() {
        // 业务逻辑
    }

    // 需要产品写入权限
    @PostMapping
    @RequiresPermission("product:write")
    public Product createProduct(@RequestBody Product product) {
        // 业务逻辑
    }

    // 需要产品删除权限
    @DeleteMapping("/{id}")
    @RequiresPermission("product:delete")
    public void deleteProduct(@PathVariable Long id) {
        // 业务逻辑
    }
}

// 权限枚举
public enum Permissions {
    PRODUCT_READ("product:read"),
    PRODUCT_WRITE("product:write"),
    PRODUCT_DELETE("product:delete"),
    USER_MANAGE("user:manage");

    private final String value;

    Permissions(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

// 使用枚举的方式
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping
    @RequiresPermission(Permissions.USER_MANAGE)
    public List<User> getAllUsers() {
        // 业务逻辑
    }
}